const Events = require('events');

class RequestParser extends Events{
    _state = this._read_request_line;
    // 进到每一个状态后，该状态处理完后，把cache一清理，进入下一个
    _cache = null;
    _message = {
        request: {
            method: '',
            path: '',
            version: '',
            headers: [],
            body: Buffer.from('')
        },
        response: {
            status: 0,
            headers: [],
            body: Buffer.from('')
        }
    };

    append(buffer){
        for(let offset = 0; offset < buffer.length; offset ++){
            this._state = this._state(buffer[offset]);
        }
    }

    // 读取请求行  methods url http版本
    _read_request_line(char){
        if(!this._cache){
            // method, url, version, CR LF
            // 一次只能存一个字符，所以用 CRFlag 的值来判断是否有 CR，然后再判断是不是LF来操作
            // [pointer, method, url, version,  CRFlag]
            this._cache = [1, '', '', '', false];
        }

        // 有空格就跳档，指到下一个位置
        if(char === 0x20){// === SP
            this._cache[0] ++;
        }else if(char === 0x0D){ // === CR
            this._cache[4] = true;
        // 有 LF，并且有 CR
        }else if(char === 0x0A && this._cache[4]){ // === LF
            this._message.request.method = this._cache[1];
            this._message.request.path = this._cache[2];
            this._message.request.version = this._cache[3];
            this._cache = null;
            return this._read_request_header_line;
        }else{ // 普通字符
            this._cache[this._cache[0]] += String.fromCharCode(char);
        }
        return this._read_request_line;
    }

    _read_request_header_line(char){
        if(!this._cache){
            // [pointer, token, content, CRFlag]
            this._cache = [1, '', '', false];
        }
        if(char === 0x3A){ // === 0x3A
            this._cache[0] ++;
        }else if(char === 0x0D){ // === CR
            this._cache[3] = true;
        }else if(char === 0x0A && this._cache[3]){ // === LF
            if(this._cache[1]){
                this._message.request.headers.push({
                    key: this._cache[1],
                    value: this._cache[2]
                });
                this._cache = null;
                return this._read_request_header_line;
            }else{
                // console.log(JSON.stringify(this._message));

                const contentLengthHeaders = this._message.request.headers.filter( item => item.key === 'Content-Length');

                if(contentLengthHeaders && 
                    contentLengthHeaders[0] && 
                    contentLengthHeaders[0].value > 0){
                    this._cache = null;
                    return this._read_request_body;
                }
                // 立刻结束，不能等下一个字符，后面没字符了
                this._cache = null;
                return this._send_finish_event();
            }
        }else{ // 普通字符
            this._cache[this._cache[0]] += String.fromCharCode(char);
        }
        return this._read_request_header_line;
    }

    _read_request_body(char){
        const contentLength = this._message.request.headers.filter(item => item.key === 'Content-Length')[0].value;

        if(!this._cache){
            // [content-length, bytes-res, content]
            this._cache = [parseInt(contentLength), 
                0, 
                new Uint8Array(parseInt(contentLength))
            ];
        }

        // 如果还没有读够，继续读取字符
        if(this._cache[1] < this._cache[0]){
            this._cache[2][this._cache[1]] = char;
            this._cache[1] ++;
            if(this._cache[1] === this._cache[0]){
                this._message.request.body = Buffer.from(this._cache[2]);
                return this._send_finish_event();
            } 
        }
        return this._read_request_body;
    }

    _send_finish_event(char){
        this.emit('finish', this._message);
        return this._end(char);
    }

    _end(char){
        return this._end;
    }
}

module.exports = RequestParser;